/*
 * Copyright 2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cc.siyecao.mapper.lambda;

import cc.siyecao.mapper.provider.Caching;
import cc.siyecao.mapper.wrapper.LambdaWrapper;
import org.apache.ibatis.annotations.*;

import java.util.List;
import java.util.Optional;

/**
 * AbstractWrapper 相关方法
 *
 * @param <T> 实体类
 * @param <E> 符合Wrapper数据结构的对象，例如 {@link LambdaMapper}，也可以是 MBG 生成 XXXWrapper 对象。
 * @author liuzh
 */
public interface LambdaMapper<T, E> {

    /**
     * 获取 AbstractWrapper 对象
     *
     * @return AbstractWrapper 对象
     */
    default LambdaWrapper<T> wrapper() {
        return new LambdaWrapper<>();
    }

    /**
     * 根据 AbstractWrapper 删除
     *
     * @param wrapper 条件
     * @return 大于等于1成功，0失败
     */
    @Lang(Caching.class)
    @DeleteProvider(type = LambdaProvider.class, method = "deleteByWrapper")
    int deleteByWrapper(E wrapper);

    /**
     * 根据 AbstractWrapper 条件批量更新实体信息
     *
     * @param entity  实体类
     * @param wrapper 条件
     * @return 大于等于1成功，0失败
     */
    @Lang(Caching.class)
    @UpdateProvider(type = LambdaProvider.class, method = "updateByWrapper")
    int updateByWrapper(@Param("entity") T entity, @Param("wrapper") E wrapper);


    /**
     * 根据 AbstractWrapper 条件批量更新实体不为空的字段
     *
     * @param entity  实体类
     * @param wrapper 条件
     * @return 大于等于1成功，0失败
     */
    @Lang(Caching.class)
    @UpdateProvider(type = LambdaProvider.class, method = "updateByWrapperSelective")
    int updateByWrapperSelective(@Param("entity") T entity, @Param("wrapper") E wrapper);

    /**
     * 根据 AbstractWrapper 条件批量查询
     *
     * @param wrapper 条件
     * @return 实体列表
     */
    @Lang(Caching.class)
    @SelectProvider(type = LambdaProvider.class, method = "selectByWrapper")
    List<T> selectByWrapper(E wrapper);

    /**
     * 根据 AbstractWrapper 条件批量查询
     *
     * @param wrapper 条件
     * @return 实体列表
     */
    @Lang(Caching.class)
    @SelectProvider(type = LambdaProvider.class, method = "selectByWrapper")
    <N> N findByWrapper(E wrapper);

    /**
     * 根据 AbstractWrapper 条件查询单个实体
     *
     * @param wrapper 条件
     * @return 单个实体，查询结果由多条时报错
     */
    @Lang(Caching.class)
    @SelectProvider(type = LambdaProvider.class, method = "selectByWrapper")
    Optional<T> selectOneByWrapper(E wrapper);

    /**
     * 根据 AbstractWrapper 条件查询总数
     *
     * @param wrapper 条件
     * @return 总数
     */
    @Lang(Caching.class)
    @SelectProvider(type = LambdaProvider.class, method = "countByWrapper")
    long countByWrapper(E wrapper);

    /* 下面的方法不需要额外的实现，算是默认方法的示例，不直接提供此类方法 */
    /*  *//**
     * 根据 AbstractWrapper 条件批量查询
     *
     * @param wrapper   条件
     * @param rowBounds 分页信息
     * @return 实体列表
     *//*
  List<T> selectByWrapper(E wrapper, RowBounds rowBounds);

  *//**
     * 根据查询条件获取第一个结果
     *
     * @param wrapper 条件
     * @return 实体
     *//*
  default Optional<T> selectFirstByWrapper(E wrapper) {
    List<T> entities = selectByWrapper(wrapper, new RowBounds(0, 1));
    if (entities.size() == 1) {
      return Optional.of(entities.get(0));
    }
    return Optional.empty();
  }

  *//**
     * 根据查询条件获取指定的前几个对象
     *
     * @param wrapper 条件
     * @param n       指定的个数
     * @return 实体
     *//*
  default List<T> selectTopNByWrapper(E wrapper, int n) {
    return selectByWrapper(wrapper, new RowBounds(0, n));
  }*/

}
